#ifndef   _DYNARRAY_H
#define   _DYNARRAY_H

#include "wx/defs.h"

#define WX_ARRAY_DEFAULT_INITIAL_SIZE    (16)

extern "C" {
  typedef int ( wxCMPFUNC_CONV *CMPFUNC )( const void* pItem1, const void* pItem2 );
}

#define  _WX_DECLARE_BASEARRAY(T, name)                   \
  class name {   \
      typedef CMPFUNC SCMPFUNC;   \
    public:                                                             \
      name();                                                           \
      name(const name& array);                                          \
      name& operator=(const name& src);                                 \
      ~name();                                                          \
      void Empty() { m_nCount = 0; }                                    \
      void Clear();                                                     \
      void Alloc(size_t n) { if ( n > m_nSize ) Realloc(n); }           \
      void Shrink();                                                    \
      size_t GetCount() const { return m_nCount; }                      \
      void SetCount(size_t n, T defval = T());                          \
      bool IsEmpty() const { return m_nCount == 0; }                    \
      size_t Count() const { return m_nCount; }                         \
      typedef T base_type;                                              \
    protected:                                                          \
      T& Item(size_t uiIndex) const { wxASSERT( uiIndex < m_nCount ); return m_pItems[uiIndex]; }   \
      T& operator[](size_t uiIndex) const { return Item(uiIndex); }     \
      int Index(T lItem, bool bFromEnd = false) const;                  \
      int Index(T lItem, CMPFUNC fnCompare) const;                      \
      size_t IndexForInsert(T lItem, CMPFUNC fnCompare) const;          \
      void Add(T lItem, size_t nInsert = 1);                            \
      size_t Add(T lItem, CMPFUNC fnCompare);                           \
      void Insert(T lItem, size_t uiIndex, size_t nInsert = 1);         \
      void Remove(T lItem);                                             \
      void RemoveAt(size_t uiIndex, size_t nRemove = 1);                \
      void Sort(CMPFUNC fnCompare);                                     \
      typedef T value_type;                                             \
      typedef value_type* iterator;                                     \
      typedef const value_type* const_iterator;                         \
      typedef value_type& reference;                                    \
      typedef const value_type& const_reference;                        \
      typedef int difference_type;                                      \
      typedef size_t size_type;                                         \
      void assign(const_iterator first, const_iterator last);           \
      void assign(size_type n, const_reference v);                      \
      size_type capacity() const { return m_nSize; }                    \
      iterator erase(iterator first, iterator last) {   \
        size_type idx = first - begin();                                \
        RemoveAt(idx, last - first);                                    \
        return begin() + idx;                                           \
      }                                                                 \
      iterator erase(iterator it) { return erase(it, it + 1); }         \
      void insert(iterator it, size_type n, const value_type& v) {   \
      Insert(v, it - begin(), n);   \
      }   \
      iterator insert(iterator it, const value_type& v = value_type()) {   \
        size_type idx = it - begin();                                   \
        Insert(v, idx);                                                 \
        return begin() + idx;                                           \
      }                                                                 \
      void insert(iterator it, const_iterator first, const_iterator last);\
      void pop_back() { RemoveAt(size() - 1); }                         \
      void push_back(const value_type& v) { Add(v); }                   \
      void reserve(size_type n) { Alloc(n); }                           \
      void resize(size_type n, value_type v = value_type()) {   \
      SetCount(n, v);   \
      }   \
      iterator begin() { return m_pItems; }                             \
      iterator end() { return m_pItems + m_nCount; }                    \
      const_iterator begin() const { return m_pItems; }                 \
      const_iterator end() const { return m_pItems + m_nCount; }        \
    public:                                                             \
      void clear() { Clear(); }                                         \
      bool empty() const { return IsEmpty(); }                          \
      size_type max_size() const { return INT_MAX; }                    \
      size_type size() const { return GetCount(); }                     \
    private:                                                            \
      void Grow(size_t nIncrement = 0);                                 \
      bool Realloc(size_t nSize);                                       \
      size_t  m_nSize,                                                  \
      m_nCount;                                                 \
      T      *m_pItems;                                                 \
  }

#define _WX_PTROP pointer operator->() const { return m_ptr; }
#define _WX_PTROP_NONE

#define _WX_DEFINE_TYPEARRAY(T, name, base)                 \
  _WX_DEFINE_TYPEARRAY_HELPER(T, name, base, _WX_PTROP)

#define _WX_DEFINE_SORTED_TYPEARRAY_2(T, name, base, defcomp, comptype)\
  wxCOMPILE_TIME_ASSERT2(sizeof(T) <= sizeof(base::base_type),          \
                         TypeTooBigToBeStoredInSorted##base,            \
                         name);                                         \
  class name : public base                                           \
  {                                                                     \
      typedef comptype SCMPFUNC;                                          \
    public:                                                               \
      name(comptype fn defcomp) { m_fnCompare = fn; }                     \
      \
      name& operator=(const name& src)                                    \
      { base* temp = (base*) this;                                      \
        (*temp) = ((const base&)src);                                   \
        m_fnCompare = src.m_fnCompare;                                  \
        return *this; }                                                 \
      \
      T& operator[](size_t uiIndex) const                                 \
      { return (T&)(base::operator[](uiIndex)); }                       \
      T& Item(size_t uiIndex) const                                       \
      { return (T&)(base::operator[](uiIndex)); }                       \
      T& Last() const                                                     \
      { return (T&)(base::operator[](size() - 1)); }                    \
      \
      int Index(T lItem) const                                            \
      { return base::Index(lItem, (CMPFUNC)m_fnCompare); }              \
      \
      size_t IndexForInsert(T lItem) const                                \
      { return base::IndexForInsert(lItem, (CMPFUNC)m_fnCompare); }     \
      \
      void AddAt(T item, size_t index)                                    \
      { base::insert(begin() + index, item); }                          \
      \
      size_t Add(T lItem)                                                 \
      { return base::Add(lItem, (CMPFUNC)m_fnCompare); }                \
      \
      void RemoveAt(size_t uiIndex, size_t nRemove = 1)                   \
      { base::erase(begin() + uiIndex, begin() + uiIndex + nRemove); }  \
      void Remove(T lItem)                                                \
      { int iIndex = Index(lItem);                                      \
        wxCHECK2_MSG( iIndex != wxNOT_FOUND, return,wxT("删除现有元素 wxArray::Remove") );   \
        base::erase(begin() + iIndex); }                                \
      \
    private:                                                              \
      comptype m_fnCompare;                                               \
  }

#define _WX_DECLARE_OBJARRAY(T, name, base)                    \
  typedef int (CMPFUNC_CONV *CMPFUNC##T)(T **pItem1, T **pItem2);          \
  class name : protected base                                           \
  {                                                                        \
      typedef int (CMPFUNC_CONV *CMPFUNC##base)(void **pItem1, void **pItem2); \
      typedef base base_array;                                                 \
    public:                                                                  \
      name() { }                                                             \
      name(const name& src);                                                 \
      name& operator=(const name& src);                                      \
      \
      ~name();                                                               \
      \
      void Alloc(size_t count) { reserve(count); }                           \
      size_t GetCount() const { return base_array::size(); }                 \
      size_t size() const { return base_array::size(); }                     \
      bool IsEmpty() const { return base_array::empty(); }                   \
      bool empty() const { return base_array::empty(); }                     \
      size_t Count() const { return base_array::size(); }                    \
      void Shrink() { base::Shrink(); }                                      \
      \
      T& operator[](size_t uiIndex) const                                    \
      { return *(T*)base::operator[](uiIndex); }                           \
      T& Item(size_t uiIndex) const                                          \
      { return *(T*)base::operator[](uiIndex); }                           \
      T& Last() const                                                        \
      { return *(T*)(base::operator[](size() - 1)); }                      \
      \
      int Index(const T& lItem, bool bFromEnd = false) const;                \
      \
      void Add(const T& lItem, size_t nInsert = 1);                          \
      void Add(const T* pItem)                                               \
      { base::push_back((T*)pItem); }                                      \
      void push_back(const T* pItem)                                         \
      { base::push_back((T*)pItem); }                                      \
      void push_back(const T& lItem)                                         \
      { Add(lItem); }                                                      \
      \
      void Insert(const T& lItem,  size_t uiIndex, size_t nInsert = 1);      \
      void Insert(const T* pItem, size_t uiIndex)                            \
      { base::insert(begin() + uiIndex, (T*)pItem); }                      \
      \
      void Empty() { DoEmpty(); base::clear(); }                             \
      void Clear() { DoEmpty(); base::clear(); }                             \
      \
      T* Detach(size_t uiIndex)                                              \
      { T* p = (T*)base::operator[](uiIndex);                              \
        base::erase(begin() + uiIndex); return p; }                        \
      void RemoveAt(size_t uiIndex, size_t nRemove = 1);                     \
      \
      void Sort(CMPFUNC##T fCmp) { base::Sort((CMPFUNC##base)fCmp); }        \
      \
    private:                                                                 \
      void DoEmpty();                                                        \
      void DoCopy(const name& src);                                          \
  }

/*#define WX_DECLARE_BASEARRAY(T, name)                             \
  WX_DECLARE_USER_EXPORTED_BASEARRAY(T, name)

#define WX_DECLARE_EXPORTED_BASEARRAY(T, name)                    \
  WX_DECLARE_USER_EXPORTED_BASEARRAY(T, name)*/

#define WX_DECLARE_USER_EXPORTED_BASEARRAY(T, name)      \
  typedef T _wxArray##name;                                     \
  _WX_DECLARE_BASEARRAY(_wxArray##name, name)

#define WX_DEFINE_TYPEARRAY(T, name, base)                        \
  WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, base)

#define WX_DEFINE_TYPEARRAY_PTR(T, name, base)                        \
  WX_DEFINE_TYPEARRAY_WITH_DECL_PTR(T, name, base)

#define WX_DEFINE_EXPORTED_TYPEARRAY(T, name, base)               \
  WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, base)

#define WX_DEFINE_EXPORTED_TYPEARRAY_PTR(T, name, base)               \
  WX_DEFINE_TYPEARRAY_WITH_DECL_PTR(T, name, base)

/*#define WX_DEFINE_USER_EXPORTED_TYPEARRAY(T, name, base) \
  WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, base)

#define WX_DEFINE_USER_EXPORTED_TYPEARRAY_PTR(T, name, base) \
  WX_DEFINE_TYPEARRAY_WITH_DECL_PTR(T, name, base)*/

#define WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, base) \
  typedef T _wxArray##name;                                   \
  _WX_DEFINE_TYPEARRAY(_wxArray##name, name, base)

#define wxARRAY_EMPTY

#define WX_DEFINE_SORTED_TYPEARRAY(T, name, base)                         \
  WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY(T, name, base)

#define WX_DEFINE_SORTED_EXPORTED_TYPEARRAY(T, name, base)                \
  WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY(T, name, base)

#define WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY(T, name, base)  \
  typedef T _wxArray##name;                                             \
  typedef int (CMPFUNC_CONV *SCMPFUNC##name)(T pItem1, T pItem2);       \
  _WX_DEFINE_SORTED_TYPEARRAY_2(_wxArray##name, name, base,wxARRAY_EMPTY, SCMPFUNC##name)

#define WX_DEFINE_SORTED_TYPEARRAY_CMP(T, cmpfunc, name, base)               \
  WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, base,     \
      wxARRAY_DEFAULT_EXPORT)

#define WX_DEFINE_SORTED_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, base)      \
  WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, base)

#define WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, base)   \
  typedef T _wxArray##name;                                                \
  typedef int (CMPFUNC_CONV *SCMPFUNC##name)(T pItem1, T pItem2);          \
  _WX_DEFINE_SORTED_TYPEARRAY_2(_wxArray##name, name, base, = cmpfunc, SCMPFUNC##name)

#define WX_DECLARE_OBJARRAY(T, name)                        \
  WX_DECLARE_USER_EXPORTED_OBJARRAY(T, name)

#define WX_DECLARE_EXPORTED_OBJARRAY(T, name)               \
  WX_DECLARE_USER_EXPORTED_OBJARRAY(T, name)

#define WX_DECLARE_OBJARRAY_WITH_DECL(T, name) \
  typedef T _wxObjArray##name;                            \
  _WX_DECLARE_OBJARRAY(_wxObjArray##name, name, wxArrayPtrVoid)

#define WX_DECLARE_USER_EXPORTED_OBJARRAY(T, name) \
  WX_DECLARE_OBJARRAY_WITH_DECL(T, name)

#define WX_DEFINE_OBJARRAY(name) DidYouIncludeArrimplCpp
/*#define WX_DEFINE_EXPORTED_OBJARRAY(name)   WX_DEFINE_OBJARRAY(name)*/
#define WX_DEFINE_USER_EXPORTED_OBJARRAY(name)   WX_DEFINE_OBJARRAY(name)

WX_DECLARE_USER_EXPORTED_BASEARRAY( const void *, wxBaseArrayPtrVoid );
WX_DECLARE_USER_EXPORTED_BASEARRAY( char, wxBaseArrayChar );
WX_DECLARE_USER_EXPORTED_BASEARRAY( short, wxBaseArrayShort );
WX_DECLARE_USER_EXPORTED_BASEARRAY( int, wxBaseArrayInt );
WX_DECLARE_USER_EXPORTED_BASEARRAY( long, wxBaseArrayLong );
WX_DECLARE_USER_EXPORTED_BASEARRAY( size_t, wxBaseArraySizeT );
WX_DECLARE_USER_EXPORTED_BASEARRAY( double, wxBaseArrayDouble );

#define WX_DEFINE_ARRAY_PTRp(T, name)                                \
  WX_DEFINE_TYPEARRAY_PTR(T, name, wxBaseArrayPtrVoid)

#define WX_DEFINE_ARRAY_PTR(type_name, name)                                                           \
  typedef type_name _wxArray_##name;                                                                     \
  typedef int (CMPFUNC_CONV *CMPFUNC_wxArray_##name)(_wxArray_##name *pItem1, _wxArray_##name *pItem2);  \
  class name : public wxBaseArrayPtrVoid {                           \
    public:                                                                                               \
      name() { }                                                                                           \
      ~name() { }                                                                                          \
      name& operator=(const name& src) {                                                                   \
        wxBaseArrayPtrVoid* temp = (wxBaseArrayPtrVoid*) this;                                             \
        (*temp) = ((const wxBaseArrayPtrVoid&)src);                                                        \
        return *this;                                                                                      \
      }                                                                                                    \
      _wxArray_##name& operator[](size_t uiIndex) const  {                                                 \
        return (_wxArray_##name&)(wxBaseArrayPtrVoid::operator[](uiIndex)); }                              \
      type_name& Item(size_t uiIndex) const  {                                                         \
        return (type_name&)(wxBaseArrayPtrVoid::operator[](uiIndex));                                  \
      }                                                                                                    \
      _wxArray_##name& Last() const  {                                                                     \
        return (_wxArray_##name&)(wxBaseArrayPtrVoid::operator[](Count() - 1)); }                          \
      int Index(_wxArray_##name lItem, bool bFromEnd = false) const  {                                     \
        return wxBaseArrayPtrVoid::Index((base_type)lItem, bFromEnd);                                      \
      }                                                                                                    \
      void Add(_wxArray_##name lItem, size_t nInsert = 1) {                                                \
        wxBaseArrayPtrVoid::Add((base_type)lItem, nInsert);                                                \
      }                                                                                                    \
      void Insert(_wxArray_##name lItem, size_t uiIndex, size_t nInsert = 1) {                             \
        wxBaseArrayPtrVoid::Insert((base_type)lItem, uiIndex, nInsert) ;                                   \
      }                                                                                                    \
      void RemoveAt(size_t uiIndex, size_t nRemove = 1) {                                                  \
        wxBaseArrayPtrVoid::RemoveAt(uiIndex, nRemove);                                                    \
      }                                                                                                    \
      void Remove(_wxArray_##name lItem) {                                                                 \
        int iIndex = Index(lItem);                                                                         \
        wxBaseArrayPtrVoid::RemoveAt((size_t)iIndex);                                                      \
      }                                                                                                    \
      void Sort(CMPFUNC_wxArray_##name fCmp) { wxBaseArrayPtrVoid::Sort((CMPFUNC)fCmp); }                  \
    private:                                                                                              \
      typedef wxBaseArrayPtrVoid::iterator biterator;                                                      \
      typedef wxBaseArrayPtrVoid::const_iterator bconst_iterator;                                          \
      typedef wxBaseArrayPtrVoid::value_type bvalue_type;                                                  \
      typedef wxBaseArrayPtrVoid::const_reference bconst_reference;                                        \
    public:                                                                                               \
      typedef base_type value_type;                                                                        \
      typedef value_type* pointer;                                                                         \
      typedef const value_type* const_pointer;                                                             \
      typedef value_type* iterator;                                                                        \
      typedef const value_type* const_iterator;                                                            \
      typedef value_type& reference;                                                                       \
      typedef const value_type& const_reference;                                                           \
      typedef wxBaseArrayPtrVoid::difference_type difference_type;                                         \
      typedef wxBaseArrayPtrVoid::size_type size_type;                                                     \
      class reverse_iterator {                                                                             \
          typedef base_type value_type;                                                                      \
          typedef value_type& reference;                                                                     \
          typedef value_type* pointer;                                                                       \
          typedef reverse_iterator itor;                                                                     \
          friend inline itor operator+(int o, const itor& it) { return it.m_ptr - o; }                       \
          friend inline itor operator+(const itor& it, int o) { return it.m_ptr - o; }                       \
          friend inline itor operator-(const itor& it, int o) { return it.m_ptr + o; }                       \
          friend inline difference_type operator-(const itor& i1, const itor& i2) {                          \
            return i1.m_ptr - i2.m_ptr;                                                                      \
          }                                                                                                  \
        public:                                                                                             \
          pointer m_ptr;                                                                                     \
          reverse_iterator() : m_ptr(NULL) { }                                                               \
          reverse_iterator(pointer ptr) : m_ptr(ptr) { }                                                     \
          reverse_iterator(const itor& it) : m_ptr(it.m_ptr) { }                                             \
          reference operator*() const { return *m_ptr; }                                                     \
          pointer operator->() const { return m_ptr; }                                                       \
          itor & operator++() { --m_ptr; return *this; }                                                     \
          const itor operator++(int) { reverse_iterator tmp = *this; --m_ptr; return tmp; }                  \
          itor & operator--() { ++m_ptr; return *this; }                                                     \
          const itor operator--(int) { itor tmp = *this; ++m_ptr; return tmp; }                              \
          bool operator ==(const itor& it) const { return m_ptr == it.m_ptr; }                               \
          bool operator !=(const itor& it) const { return m_ptr != it.m_ptr; }                               \
      };                                                                                                   \
      class const_reverse_iterator {                                                                       \
          typedef base_type value_type;                                                                      \
          typedef const value_type& reference;                                                               \
          typedef const value_type* pointer;                                                                 \
          typedef const_reverse_iterator itor;                                                               \
          friend inline itor operator+(int o, const itor & it) { return it.m_ptr - o; }                      \
          friend inline itor operator+(const itor & it, int o) { return it.m_ptr - o; }                      \
          friend inline itor operator-(const itor & it, int o) { return it.m_ptr + o; }                      \
          friend inline difference_type operator-(const itor & i1, const itor & i2) {                        \
            return i1.m_ptr - i2.m_ptr;                                                                      \
          }                                                                                                  \
        public:                                                                                             \
          pointer m_ptr;                                                                                     \
          const_reverse_iterator() : m_ptr(NULL) { }                                                         \
          const_reverse_iterator(pointer ptr) : m_ptr(ptr) { }                                               \
          const_reverse_iterator(const itor & it) : m_ptr(it.m_ptr) { }                                      \
          const_reverse_iterator(const reverse_iterator & it) : m_ptr(it.m_ptr) { }                          \
          reference operator*() const { return *m_ptr; }                                                     \
          pointer operator->() const { return m_ptr; }                                                       \
          itor & operator++() { --m_ptr; return *this; }                                                     \
          const itor operator++(int) { itor tmp = *this; --m_ptr; return tmp; }                              \
          itor & operator--() { ++m_ptr; return *this; }                                                     \
          const itor operator--(int) { itor tmp = *this; ++m_ptr; return tmp; }                              \
          bool operator ==(const itor & it) const { return m_ptr == it.m_ptr; }                              \
          bool operator !=(const itor & it) const { return m_ptr != it.m_ptr; }                              \
      };                                                                                                   \
      \
      name(size_type n, const_reference v) { assign(n, v); }                                               \
      name(const_iterator first, const_iterator last) { assign(first, last); }                             \
      void assign(const_iterator first, const_iterator last) {                                             \
        wxBaseArrayPtrVoid::assign((bconst_iterator)first, (bconst_iterator)last);                         \
      }                                                                                                    \
      void assign(size_type n, const_reference v) { wxBaseArrayPtrVoid::assign(n, (bconst_reference)v); }  \
      reference back() { return *(end() - 1); }                                                            \
      const_reference back() const { return *(end() - 1); }                                                \
      iterator begin() { return (iterator)wxBaseArrayPtrVoid::begin(); }                                   \
      const_iterator begin() const { return (const_iterator)wxBaseArrayPtrVoid::begin(); }                 \
      size_type capacity() const { return wxBaseArrayPtrVoid::capacity(); }                                \
      iterator end() { return (iterator)wxBaseArrayPtrVoid::end(); }                                       \
      const_iterator end() const { return (const_iterator)wxBaseArrayPtrVoid::end(); }                     \
      iterator erase(iterator first, iterator last) {                                                      \
        return (iterator)wxBaseArrayPtrVoid::erase((biterator)first, (biterator)last);                     \
      }                                                                                                    \
      iterator erase(iterator it) { return (iterator)wxBaseArrayPtrVoid::erase((biterator)it); }           \
      reference front() { return *begin(); }                                                               \
      const_reference front() const { return *begin(); }                                                   \
      void insert(iterator it, size_type n, const_reference v) {                                           \
        wxBaseArrayPtrVoid::insert((biterator)it, n, (bconst_reference)v);                                 \
      }                                                                                                    \
      iterator insert(iterator it, const_reference v = value_type()) {                                     \
        return (iterator)wxBaseArrayPtrVoid::insert((biterator)it, (bconst_reference)v);                   \
      }                                                                                                    \
      void insert(iterator it, const_iterator first, const_iterator last) {                                \
        \
        wxBaseArrayPtrVoid::insert((biterator)it, (bconst_iterator)first, (bconst_iterator)last);          \
        \
      }                                                                                                    \
      void pop_back() { wxBaseArrayPtrVoid::pop_back(); }                                                  \
      void push_back(const_reference v) { wxBaseArrayPtrVoid::push_back((bconst_reference)v); }            \
      reverse_iterator rbegin() { return reverse_iterator(end() - 1); }                                    \
      const_reverse_iterator rbegin() const;                                                               \
      reverse_iterator rend() { return reverse_iterator(begin() - 1); }                                    \
      const_reverse_iterator rend() const;                                                                 \
      void reserve(size_type n) { wxBaseArrayPtrVoid::reserve(n); }                                        \
      void resize(size_type n, value_type v = value_type()) { wxBaseArrayPtrVoid::resize(n, v); }          \
  };

#define WX_DEFINE_ARRAY(T, name)                                       \
  WX_DEFINE_TYPEARRAY(T, name, wxBaseArrayPtrVoid)

#define WX_DEFINE_EXPORTED_ARRAY(T, name)                              \
  WX_DEFINE_EXPORTED_TYPEARRAY(T, name, wxBaseArrayPtrVoid)

#define WX_DEFINE_EXPORTED_ARRAY_PTR(T, name)                       \
  WX_DEFINE_EXPORTED_TYPEARRAY_PTR(T, name, wxBaseArrayPtrVoid)

#define WX_DEFINE_ARRAY_WITH_DECL_PTR(T, name)                \
  WX_DEFINE_TYPEARRAY_WITH_DECL_PTR(T, name, wxBaseArrayPtrVoid)

#define WX_DEFINE_USER_EXPORTED_ARRAY(T, name)                \
  WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, wxBaseArrayPtrVoid)

#define WX_DEFINE_USER_EXPORTED_ARRAY_PTR(T, name)         \
  WX_DEFINE_TYPEARRAY_WITH_DECL_PTR(T, name, wxBaseArrayPtrVoid)

#define WX_DEFINE_ARRAY_CHAR(T, name)                                 \
  WX_DEFINE_TYPEARRAY_PTR(T, name, wxBaseArrayChar)

#define WX_DEFINE_EXPORTED_ARRAY_CHAR(T, name)                        \
  WX_DEFINE_EXPORTED_TYPEARRAY_PTR(T, name, wxBaseArrayChar)

#define WX_DEFINE_USER_EXPORTED_ARRAY_CHAR(T, name)          \
  WX_DEFINE_TYPEARRAY_WITH_DECL_PTR(T, name, wxBaseArrayChar)

#define WX_DEFINE_ARRAY_SHORT(T, name)                                 \
  WX_DEFINE_TYPEARRAY_PTR(T, name, wxBaseArrayShort)

#define WX_DEFINE_EXPORTED_ARRAY_SHORT(T, name)                        \
  WX_DEFINE_EXPORTED_TYPEARRAY_PTR(T, name, wxBaseArrayShort)

#define WX_DEFINE_ARRAY_INT(T, name)                                   \
  WX_DEFINE_TYPEARRAY_PTR(T, name, wxBaseArrayInt)

#define WX_DEFINE_EXPORTED_ARRAY_INT(T, name)                          \
  WX_DEFINE_EXPORTED_TYPEARRAY_PTR(T, name, wxBaseArrayInt)

#define WX_DEFINE_USER_EXPORTED_ARRAY_INT(T, name)            \
  WX_DEFINE_TYPEARRAY_WITH_DECL_PTR(T, name, wxBaseArrayInt)

#define WX_DEFINE_ARRAY_LONG(T, name)                                  \
  WX_DEFINE_TYPEARRAY_PTR(T, name, wxBaseArrayLong)

#define WX_DEFINE_EXPORTED_ARRAY_LONG(T, name)                         \
  WX_DEFINE_EXPORTED_TYPEARRAY_PTR(T, name, wxBaseArrayLong)

#define WX_DEFINE_USER_EXPORTED_ARRAY_LONG(T, name)           \
  WX_DEFINE_TYPEARRAY_WITH_DECL_PTR(T, name, wxBaseArrayLong)

#define WX_DEFINE_ARRAY_SIZE_T(T, name)                                  \
  WX_DEFINE_TYPEARRAY_PTR(T, name, wxBaseArraySizeT)

#define WX_DEFINE_EXPORTED_ARRAY_SIZE_T(T, name)                         \
  WX_DEFINE_EXPORTED_TYPEARRAY_PTR(T, name, wxBaseArraySizeT)

#define WX_DEFINE_USER_EXPORTED_ARRAY_SIZE_T(T, name)           \
  WX_DEFINE_TYPEARRAY_WITH_DECL_PTR(T, name, wxBaseArraySizeT)

#define WX_DEFINE_ARRAY_DOUBLE(T, name)                                \
  WX_DEFINE_TYPEARRAY_PTR(T, name, wxBaseArrayDouble)

#define WX_DEFINE_EXPORTED_ARRAY_DOUBLE(T, name)                       \
  WX_DEFINE_EXPORTED_TYPEARRAY_PTR(T, name, wxBaseArrayDouble)

#define WX_DEFINE_USER_EXPORTED_ARRAY_DOUBLE(T, name)         \
  WX_DEFINE_TYPEARRAY_WITH_DECL_PTR(T, name, wxBaseArrayDouble)

#define WX_DEFINE_SORTED_ARRAY(T, name)                                \
  WX_DEFINE_SORTED_TYPEARRAY(T, name, wxBaseArrayPtrVoid)

#define WX_DEFINE_SORTED_EXPORTED_ARRAY(T, name)                       \
  WX_DEFINE_SORTED_EXPORTED_TYPEARRAY(T, name, wxBaseArrayPtrVoid)

#define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY(T, name)         \
  WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY(T, name, wxBaseArrayPtrVoid)

#define WX_DEFINE_SORTED_ARRAY_CHAR(T, name)                          \
  WX_DEFINE_SORTED_TYPEARRAY(T, name, wxBaseArrayChar)

#define WX_DEFINE_SORTED_EXPORTED_ARRAY_CHAR(T, name)                 \
  WX_DEFINE_SORTED_EXPORTED_TYPEARRAY(T, name, wxBaseArrayChar)

#define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_CHAR(T, name)   \
  WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY(T, name, wxBaseArrayChar)

#define WX_DEFINE_SORTED_ARRAY_SHORT(T, name)                          \
  WX_DEFINE_SORTED_TYPEARRAY(T, name, wxBaseArrayShort)

#define WX_DEFINE_SORTED_EXPORTED_ARRAY_SHORT(T, name)                 \
  WX_DEFINE_SORTED_EXPORTED_TYPEARRAY(T, name, wxBaseArrayShort)

#define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_SHORT(T, name)   \
  WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY(T, name, wxBaseArrayShort)

#define WX_DEFINE_SORTED_ARRAY_INT(T, name)                            \
  WX_DEFINE_SORTED_TYPEARRAY(T, name, wxBaseArrayInt)

#define WX_DEFINE_SORTED_EXPORTED_ARRAY_INT(T, name)                   \
  WX_DEFINE_SORTED_EXPORTED_TYPEARRAY(T, name, wxBaseArrayInt)

#define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_INT(T, name)     \
  WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY(T, name, wxBaseArrayInt)

#define WX_DEFINE_SORTED_ARRAY_LONG(T, name)                           \
  WX_DEFINE_SORTED_TYPEARRAY(T, name, wxBaseArrayLong)

#define WX_DEFINE_SORTED_EXPORTED_ARRAY_LONG(T, name)                  \
  WX_DEFINE_SORTED_EXPORTED_TYPEARRAY(T, name, wxBaseArrayLong)

#define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_LONG(T, name)    \
  WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY(T, name, wxBaseArrayLong)

#define WX_DEFINE_SORTED_ARRAY_SIZE_T(T, name)                           \
  WX_DEFINE_SORTED_TYPEARRAY(T, name, wxBaseArraySizeT)

#define WX_DEFINE_SORTED_EXPORTED_ARRAY_SIZE_T(T, name)                  \
  WX_DEFINE_SORTED_EXPORTED_TYPEARRAY(T, name, wxBaseArraySizeT)

#define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_SIZE_T(T, name)    \
  WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY(T, name, wxBaseArraySizeT)

#define WX_DEFINE_SORTED_ARRAY_CMP(T, cmpfunc, name)                   \
  WX_DEFINE_SORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArrayPtrVoid)

#define WX_DEFINE_SORTED_EXPORTED_ARRAY_CMP(T, cmpfunc, name)          \
  WX_DEFINE_SORTED_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArrayPtrVoid)

#define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_CMP(T, cmpfunc,name, expmode)    \
  WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name,wxBaseArrayPtrVoid,wxARRAY_EMPTY expmode)

#define WX_DEFINE_SORTED_ARRAY_CMP_CHAR(T, cmpfunc, name)             \
  WX_DEFINE_SORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArrayChar)

#define WX_DEFINE_SORTED_EXPORTED_ARRAY_CMP_CHAR(T, cmpfunc, name)    \
  WX_DEFINE_SORTED_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArrayChar)

#define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_CMP_CHAR(T, cmpfunc,name, expmode)  \
  WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name,wxBaseArrayChar,wxARRAY_EMPTY expmode)

#define WX_DEFINE_SORTED_ARRAY_CMP_SHORT(T, cmpfunc, name)             \
  WX_DEFINE_SORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArrayShort)

#define WX_DEFINE_SORTED_EXPORTED_ARRAY_CMP_SHORT(T, cmpfunc, name)    \
  WX_DEFINE_SORTED_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArrayShort)

#define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_CMP_SHORT(T, cmpfunc,name, expmode)  \
  WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name,wxBaseArrayShort,wxARRAY_EMPTY expmode)

#define WX_DEFINE_SORTED_ARRAY_CMP_INT(T, cmpfunc, name)               \
  WX_DEFINE_SORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArrayInt)

#define WX_DEFINE_SORTED_EXPORTED_ARRAY_CMP_INT(T, cmpfunc, name)      \
  WX_DEFINE_SORTED_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArrayInt)

#define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_CMP_INT(T, cmpfunc,       \
    name, expmode)    \
WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name,wxBaseArrayInt,wxARRAY_EMPTY expmode)

#define WX_DEFINE_SORTED_ARRAY_CMP_LONG(T, cmpfunc, name)              \
  WX_DEFINE_SORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArrayLong)

#define WX_DEFINE_SORTED_EXPORTED_ARRAY_CMP_LONG(T, cmpfunc, name)     \
  WX_DEFINE_SORTED_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArrayLong)

#define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_CMP_LONG(T, cmpfunc,name, expmode)   \
  WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name,wxBaseArrayLong,wxARRAY_EMPTY expmode)

#define WX_DEFINE_SORTED_ARRAY_CMP_SIZE_T(T, cmpfunc, name)              \
  WX_DEFINE_SORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArraySizeT)

#define WX_DEFINE_SORTED_EXPORTED_ARRAY_CMP_SIZE_T(T, cmpfunc, name)     \
  WX_DEFINE_SORTED_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, wxBaseArraySizeT)

#define WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_CMP_SIZE_T(T, cmpfunc,name)   \
  WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name,wxBaseArraySizeT)

#define WX_DEFINE_USER_EXPORTED_ARRAY_SHORT(T, name)          \
  WX_DEFINE_TYPEARRAY_WITH_DECL_PTR(T, name,wxBaseArrayShort)

#define WX_DEFINE_TYPEARRAY_WITH_DECL_PTR(T, name,classdecl) \
  typedef T _wxArray##name;                                          \
  _WX_DEFINE_TYPEARRAY_PTR(_wxArray##name, name, classdecl)

#define _WX_DEFINE_TYPEARRAY(T, name, base)                 \
  _WX_DEFINE_TYPEARRAY_HELPER(T, name, base, _WX_PTROP)

#define _WX_DEFINE_TYPEARRAY_PTR(T, name, base)          \
  _WX_DEFINE_TYPEARRAY_HELPER(T, name, base, _WX_PTROP_NONE)

#define  _WX_DEFINE_TYPEARRAY_HELPER(T, name, base, ptrop)  \
  wxCOMPILE_TIME_ASSERT2(sizeof(T) <= sizeof(base::base_type), TypeTooBigToBeStoredIn##base, name);   \
  typedef int (CMPFUNC_CONV *CMPFUNC##T)(T *pItem1, T *pItem2);         \
  class name : public base {   \
    public:                                                               \
      name() { }                                                          \
      ~name() { }                                                         \
      name& operator=(const name& src) { base* temp = (base*) this;   \
        (*temp) = ((const base&)src);                                   \
        return *this; }                                                 \
      T& operator[](size_t uiIndex) const { return (T&)(base::operator[](uiIndex)); }   \
      T& Item(size_t uiIndex) const                                       \
      { return (T&)(base::operator[](uiIndex)); }   \
      T& Last() const  { return (T&)(base::operator[](Count() - 1)); }   \
      int Index(T lItem, bool bFromEnd = false) const { return base::Index((base_type)lItem, bFromEnd); }   \
      void Add(T lItem, size_t nInsert = 1) { base::Add((base_type)lItem, nInsert); }                         \
      void Insert(T lItem, size_t uiIndex, size_t nInsert = 1)            \
      { base::Insert((base_type)lItem, uiIndex, nInsert) ; }            \
      void RemoveAt(size_t uiIndex, size_t nRemove = 1) { base::RemoveAt(uiIndex, nRemove); }   \
      void Remove(T lItem) { int iIndex = Index(lItem);   \
        wxCHECK2_MSG( iIndex != wxNOT_FOUND, return, wxT("删除现有元素 wxArray::Remove"));   \
        base::RemoveAt((size_t)iIndex); }                               \
      void Sort(CMPFUNC##T fCmp) { base::Sort((CMPFUNC)fCmp); }           \
    private:                                                              \
      typedef base::iterator biterator;                                   \
      typedef base::const_iterator bconst_iterator;                       \
      typedef base::value_type bvalue_type;                               \
      typedef base::const_reference bconst_reference;                     \
    public:                                                               \
      typedef T value_type;                                               \
      typedef value_type* pointer;                                        \
      typedef const value_type* const_pointer;                            \
      typedef value_type* iterator;                                       \
      typedef const value_type* const_iterator;                           \
      typedef value_type& reference;                                      \
      typedef const value_type& const_reference;                          \
      typedef base::difference_type difference_type;                      \
      typedef base::size_type size_type;                                  \
      class reverse_iterator {   \
          typedef T value_type;                                             \
          typedef value_type& reference;                                    \
          typedef value_type* pointer;                                      \
          typedef reverse_iterator itor;                                    \
          friend inline itor operator+(int o, const itor& it) { return it.m_ptr - o; }   \
          friend inline itor operator+(const itor& it, int o) { return it.m_ptr - o; }   \
          friend inline itor operator-(const itor& it, int o) { return it.m_ptr + o; }   \
          friend inline difference_type operator-(const itor& i1,const itor& i2) { return i1.m_ptr - i2.m_ptr; }   \
        public:                                                             \
          pointer m_ptr;                                                    \
          reverse_iterator() : m_ptr(NULL) { }                              \
          reverse_iterator(pointer ptr) : m_ptr(ptr) { }                    \
          reverse_iterator(const itor& it) : m_ptr(it.m_ptr) { }            \
          reference operator*() const { return *m_ptr; }                    \
          ptrop                                                             \
          itor& operator++() { --m_ptr; return *this; }                     \
          const itor operator++(int) { reverse_iterator tmp = *this; --m_ptr; return tmp; }   \
          itor& operator--() { ++m_ptr; return *this; }                     \
          const itor operator--(int) { itor tmp = *this; ++m_ptr; return tmp; } \
          bool operator ==(const itor& it) const { return m_ptr == it.m_ptr; } \
          bool operator !=(const itor& it) const { return m_ptr != it.m_ptr; } \
      };   \
      class const_reverse_iterator {   \
          typedef T value_type;                                             \
          typedef const value_type& reference;                              \
          typedef const value_type* pointer;                                \
          typedef const_reverse_iterator itor;                              \
          friend inline itor operator+(int o, const itor& it) { return it.m_ptr - o; }   \
          friend inline itor operator+(const itor& it, int o) { return it.m_ptr - o; }   \
          friend inline itor operator-(const itor& it, int o) { return it.m_ptr + o; }   \
          friend inline difference_type operator-(const itor& i1, const itor& i2) { return i1.m_ptr - i2.m_ptr; }   \
        public:                                                             \
          pointer m_ptr;                                                    \
          const_reverse_iterator() : m_ptr(NULL) { }                        \
          const_reverse_iterator(pointer ptr) : m_ptr(ptr) { }              \
          const_reverse_iterator(const itor& it) : m_ptr(it.m_ptr) { }      \
          const_reverse_iterator(const reverse_iterator& it) : m_ptr(it.m_ptr) { } \
          reference operator*() const { return *m_ptr; }                    \
          ptrop                                                             \
          itor& operator++() { --m_ptr; return *this; }                     \
          const itor operator++(int) { itor tmp = *this; --m_ptr; return tmp; }   \
          itor& operator--() { ++m_ptr; return *this; }                     \
          const itor operator--(int) { itor tmp = *this; ++m_ptr; return tmp; } \
          bool operator ==(const itor& it) const { return m_ptr == it.m_ptr; } \
          bool operator !=(const itor& it) const { return m_ptr != it.m_ptr; } \
      };  \
      name(size_type n, const_reference v) { assign(n, v); }              \
      name(const_iterator first, const_iterator last) { assign(first, last); }   \
      void assign(const_iterator first, const_iterator last)              \
      { base::assign((bconst_iterator)first, (bconst_iterator)last); }  \
      void assign(size_type n, const_reference v) { base::assign(n, (bconst_reference)v); }   \
      reference back() { return *(end() - 1); }                           \
      const_reference back() const { return *(end() - 1); }               \
      iterator begin() { return (iterator)base::begin(); }                \
      const_iterator begin() const { return (const_iterator)base::begin(); } \
      size_type capacity() const { return base::capacity(); }             \
      iterator end() { return (iterator)base::end(); }                    \
      const_iterator end() const { return (const_iterator)base::end(); }  \
      iterator erase(iterator first, iterator last)                       \
      { return (iterator)base::erase((biterator)first, (biterator)last); } \
      iterator erase(iterator it) { return (iterator)base::erase((biterator)it); }   \
      reference front() { return *begin(); }                              \
      const_reference front() const { return *begin(); }                  \
      void insert(iterator it, size_type n, const_reference v)            \
      { base::insert((biterator)it, n, (bconst_reference)v); }          \
      iterator insert(iterator it, const_reference v = value_type())      \
      { return (iterator)base::insert((biterator)it, (bconst_reference)v); } \
      void insert(iterator it, const_iterator first, const_iterator last) \
      { base::insert((biterator)it, (bconst_iterator)first, (bconst_iterator)last); }   \
      void pop_back() { base::pop_back(); }                               \
      void push_back(const_reference v) { base::push_back((bconst_reference)v); }  \
      reverse_iterator rbegin() { return reverse_iterator(end() - 1); }   \
      const_reverse_iterator rbegin() const;                              \
      reverse_iterator rend() { return reverse_iterator(begin() - 1); }   \
      const_reverse_iterator rend() const;                                \
      void reserve(size_type n) { base::reserve(n); }                     \
      void resize(size_type n, value_type v = value_type()) { base::resize(n, v); }   \
  }



WX_DEFINE_USER_EXPORTED_ARRAY_SHORT( short, wxArrayShort );
WX_DEFINE_USER_EXPORTED_ARRAY_INT( int, wxArrayInt );
WX_DEFINE_USER_EXPORTED_ARRAY_DOUBLE( double, wxArrayDoubleE );
WX_DEFINE_USER_EXPORTED_ARRAY_LONG( long, wxArrayLong );
WX_DEFINE_USER_EXPORTED_ARRAY_PTR( void *, wxArrayPtrVoid );


#define WX_PREPEND_ARRAY(array, other)                                        \
  {                                                                         \
    size_t wxAAcnt = (other).size();                                      \
    (array).Alloc(wxAAcnt);                                               \
    for ( size_t wxAAn = 0; wxAAn < wxAAcnt; wxAAn++ )                    \
    {                                                                     \
      (array).Insert((other)[wxAAn], wxAAn);                            \
    }                                                                     \
  }

#define WX_APPEND_ARRAY(array, other)                                         \
  {                                                                         \
    size_t wxAAcnt = (other).size();                                      \
    (array).Alloc(wxAAcnt);                                               \
    for ( size_t wxAAn = 0; wxAAn < wxAAcnt; wxAAn++ )                    \
    {                                                                     \
      (array).push_back((other)[wxAAn]);                                \
    }                                                                     \
  }

#define WX_CLEAR_ARRAY(array)                                                 \
  {                                                                         \
    size_t wxAAcnt = (array).size();                                      \
    for ( size_t wxAAn = 0; wxAAn < wxAAcnt; wxAAn++ )                    \
    {                                                                     \
      delete (array)[wxAAn];                                            \
    }                                                                     \
    \
    (array).clear();                                                      \
  }

#endif
